/*******************************************************************
*
*    DESCRIPTION:The entry of coolnet
*
*    AUTHOR:LiuHui
*
*    HISTORY:
*
*    DATE:1/20/2007
*
*******************************************************************/
/** include files **/
#include <config.h>
#include <debug.h>
#include <header.h>
#include <xml_util.h>
#include <rules.h>
#include <gui.h>
/** local definitions **/

/* default settings */

/** external functions **/
extern void *packet_monitor(void *data);
/** external data **/

/** internal functions **/
static void goodbye(void);
static void sig_int_func(int sig);
static void detect_environment(void);
static void detect_doule_start();
static int process_is_running();
/** public data **/

/** private data **/

/** public functions **/
int main(int argc, char *argv[])
{
  int result = 0;
  pthread_t pid;
  /*detect environment*/
  detect_environment();
  /*xml init*/
  init_conf_xml();
  /*detect double start*/
  detect_doule_start();
  /*rules init*/
  init_default_rules();
  if (is_first_time_start())
  {
    /*Show  guide*/
    /*Set have started*/
    set_program_have_started();
  }
  /*gtk init*/
  g_thread_init (NULL);
  gdk_threads_init ();
  gdk_threads_enter ();
  /*i18n*/
  bindtextdomain(PACKAGE,LOCALEDIR);
  textdomain(PACKAGE);
  gtk_init(&argc, &argv);
  /*show tray icon*/
  init_tray_icon();
  /*start up packet monitor thread*/
  result = pthread_create(&pid, NULL, packet_monitor, NULL);
  if (result != 0)
  {
    __ERROR_MSG("Error when create thread\n");
    exit(1);
  }
  /*Treat error*/
  atexit(goodbye);
  signal(SIGINT, sig_int_func);

  gtk_main();
  gdk_threads_leave ();

  return 0;
}

static void goodbye(void)
{
  clean_filter_table();
}
static void sig_int_func(int sig)
{
  exit(1);
}

static int is_root(void)
{
    if (geteuid()==0) {
        return 1;
    }
    else
    {
        return 0;
    }

  
}


/*
 *Function Name:is_module_exist
 *
 *Parameters:
 *
 *Description:if it returns,it always succed,or the whole app exits.
 *
 *Returns: 
 */

static void is_module_exist(char * mod_name)
{
  char cmd[1024]={0};
  int rst;

  sprintf(cmd,"modprobe %s 1>/dev/null 2>&1",mod_name);
  rst=system(cmd);
  if (rst)
  {
    __ERROR_MSG("Error when try loading %s.\n",mod_name);
    exit(1);
  }

  return;
}

/*
 *Function Name:is_specdesktop_running
 *
 *Parameters:
 *
 *Description:
 *
 *Returns:	1 if desktop_name is running
 *			otherwise,0
 */

static int is_specdesktop_running(char *desktop_name)
{
  char cmd[1024]={0};
  int rst;
  sprintf(cmd,"ps aux|grep -v grep|grep -i %s 1>/dev/null 2>&1",desktop_name);
  rst=system(cmd);

  return(rst==0)?1:0;
}




/*
 *detect if is root
 *detect if netfilter support exist
 *detect  if some  modules exist.eg,conntrack, ftp etc.
 *detect which Desktop enviroment customer is using
*/
static void detect_environment(void)
{
  if (is_root()==0)
  {
    __ERROR_MSG("Only root can start this program.\n");
    exit(1);
  }


  char *mod_list[]={
    "ip_tables",
    "ip_queue",
    "ip_conntrack",     
    (char*)NULL

  };

  int i=0;
  while (mod_list[i]!=(char*)NULL)
  {
    is_module_exist(mod_list[i]);
    i++;
  }

  if (is_specdesktop_running("gnome")==1)
  {
    //

  }
  else if (is_specdesktop_running("kde")==1)
  {
    //
  }
  return;
}

static void detect_doule_start()
{
  if (process_is_running())
  {
    __ERROR_MSG("Coolnet already started\n");
    exit(0);
  }
}

#define CHECK_PROCESS_LEN     8
#define CHECK_PROCESS_PATH    "/tmp/COOLNET2.pid"

/*check process running
 * return 0:first running
 * return -1:twice running
 * */
static int process_is_running()
{
  int fd = -1;
  int ret = -1;
  int size = -1;
  char buf[CHECK_PROCESS_LEN] = {0};
  pid_t pid;

  pid = getpid();
  snprintf(buf, CHECK_PROCESS_LEN, "%d", pid);

  fd = open(CHECK_PROCESS_PATH, O_WRONLY | O_CREAT, 0666);
  if (fd < 0)
  {
    __DEBUG_MSG("open fail");
    return -1;
  }

  ret = lockf(fd, F_TLOCK, CHECK_PROCESS_LEN);
  if (ret)
  {
    return -1;
  }
  ret = lockf(fd, F_LOCK, CHECK_PROCESS_LEN);
  if (ret)
  {
    return -1;
  }

  size = write(fd, buf, sizeof(buf));
  if (size != sizeof(buf))
  {
    __DEBUG_MSG("write");
    return -1;
  }
  return 0;

}
